﻿using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

namespace QFramework
{
    public class StateManagerEditor : EditorWindow {

        private int                             m_CurrentIndex;
        private string[]                        m_ScriptList;
        private string[]                        m_StateList;
        private Vector2                         One_scrollPos;
        private Vector2                         Two_scorllPos;
        private Vector2                         Three_scorllpos;
        private Vector2                         m_TempMousePoint;
        private Texture2D                       m_NormalTexture;
        private Texture2D                       m_HoverTexture;
        private Texture2D                       m_ArrowTexture;

        private bool                            m_IsShowArrow = false;
        private Rect                            m_MousePoint;
        private static GUIStyle                 tempStyle;
        private ScriptData                      m_CurrentScript;
        private Rect                            m_EnterRect=new Rect(10, 120, 80, 40);
        private StateData                       m_CurrentSelect;
        private string                          m_ScirptName="ScriptName";
        private string                          m_AddKey="IsKey";
        private Vector2                         m_Scale=new Vector2 (1,1);
        private Dictionary<int,Vector3[]>       m_Bezier;
        private KeyData                         m_KeyData;
        private Vector2                         m_KeyScrollPos;
        private Rect                            m_WindowsRect;
        [MenuItem("Assets/StateManager")]
        static void Open()
        {
            StateManagerEditor tempWindws = (StateManagerEditor)EditorWindow.GetWindowWithRect(typeof(StateManagerEditor), new Rect(0, 0, 900, 530));
            tempWindws.titleContent = new GUIContent("StateManager");
            tempWindws.Init();
            tempWindws.Show();
        }

        #region 初始化

        void Init()
        {
            m_NormalTexture = Resources.Load("StateManagerNormal") as Texture2D;
            m_HoverTexture = Resources.Load("StateManagerHover") as Texture2D;
            m_ArrowTexture = Resources.Load("Arrow") as Texture2D;

            tempStyle = new GUIStyle();
            tempStyle.normal.textColor = Color.green;
            tempStyle.normal.background = m_NormalTexture;
            tempStyle.active.background = m_HoverTexture;
            tempStyle.alignment = TextAnchor.MiddleCenter;

            m_ScriptList = ScriptData.GetScriptList();
            if (m_ScriptList == null || m_ScriptList.Length == 0)
            {
                m_CurrentScript = EntityCodeGenerator.CreateCode(ScriptData.masterName);
            }
            else
            {
                if (m_ScriptList[0] != ScriptData.masterName)
                {
                    int index=0;
                    for (int i = 0; i < m_ScriptList.Length; i++)
                    {
                        if (m_ScriptList[i] == ((ScriptData.masterName) + ".cs"))
                        {
                            index = i;
                        }
                    }
                    string temp = m_ScriptList[0];
                    m_ScriptList[0] = ((ScriptData.masterName) + ".cs");
                    m_ScriptList[index] = temp;
                }
            }
            m_ScirptName = "ScriptName";
            m_Bezier = new Dictionary<int, Vector3[]>();
            m_KeyData = new KeyData();
            m_KeyData.ReadData();
            m_StateList = StateData.GetScriptList();
            m_WindowsRect = new Rect(0,60,750,470);
        }

        #endregion

        void OnDisable()
        {
            if (m_NormalTexture)
                Resources.UnloadAsset(m_NormalTexture);
            if (m_HoverTexture)
                Resources.UnloadAsset(m_HoverTexture);
            if (m_ArrowTexture)
                Resources.UnloadAsset(m_ArrowTexture);
        }

        void OnGUI()
        {
            
            EventDeal();

            EditorGUILayout.BeginVertical();

            GUILayout.BeginArea(new Rect(new Vector2(100, 20), new Vector2(600, 40)));
            {
                if (m_ScriptList == null || m_ScriptList.Length == 0)
                {
                    try
                    {
                        m_ScriptList = ScriptData.GetScriptList();
                        if (m_ScriptList[m_CurrentIndex] != ScriptData.masterName)
                        {
                            for (int i = 0; i < m_ScriptList.Length; i++)
                            {
                                if (m_ScriptList[i].Equals(ScriptData.masterName))
                                {
                                    m_CurrentIndex = i;
                                    Debug.Log("设置当前下标");
                                }
                            }
                        }
                    }
                    catch { }
                }

                m_CurrentIndex = EditorGUILayout.Popup(m_CurrentIndex, m_ScriptList, GUILayout.Width(200), GUILayout.Height(20));
               
                if(m_CurrentScript!=null)
                if (m_ScriptList[m_CurrentIndex] != (m_CurrentScript.Name+".cs"))
                {
                    m_CurrentScript = EntityCodeGenerator.GetData(m_ScriptList[m_CurrentIndex]);
                }
                
                m_ScirptName = GUI.TextField(new Rect(230, 0, 100, 20), m_ScirptName);
                if (GUI.Button(new Rect(330,0,40,20),"√"))
                {                   
                    bool isHasScript=false;
                    for (int i = 0; i < m_ScriptList.Length; i++)
                    {
                        if (m_ScriptList[i].Equals(m_ScirptName+".cs"))
                        {
                            isHasScript = true;
                        }
                    }
                    if (!isHasScript)
                    {
                        EntityCodeGenerator.CreateCode(m_ScirptName);
                        m_ScriptList = ScriptData.GetScriptList();
                        for (int i = 0; i < m_ScriptList.Length; i++)
                        {
                            if (m_ScriptList[i].Equals(m_ScirptName+".cs"))
                            {
                                m_CurrentIndex = i;
                                break;
                            }
                        }
                    }
                    else
                    {
                        this.ShowNotification(new GUIContent("Names Conflict"));
                    }
                }
            }
             
            GUILayout.EndArea();
            EditorGUILayout.EndVertical();

            GUILayout.BeginArea(new Rect(new Vector2(760, 0), new Vector2(140, 530)));
            {
                EditorGUILayout.BeginVertical();

                Two_scorllPos = EditorGUILayout.BeginScrollView(Two_scorllPos, false, false, GUILayout.Width(140), GUILayout.Height(265));

                for (int i = 0; i < m_StateList.Length; i++)
                {

                    GUIStyle m_state = "CapsuleButton";
                    m_state.active.textColor = Color.red;
                    m_state.active.background = m_HoverTexture;

                    if (GUI.Button(new Rect(0, 40 * i + 30, 100, 40), m_StateList[i], m_state))
                    {
                        Debug.Log("heleo");
                    }
                }

                EditorGUILayout.EndScrollView();

                Three_scorllpos = EditorGUILayout.BeginScrollView(Three_scorllpos, true, true, GUILayout.Width(140), GUILayout.Height(245));

                GUILayout.Space(10);

                for (int i = 0; i < m_KeyData.GetKey().Count; i++)
                {
                    GUIStyle tempStyle = new GUIStyle();
                    tempStyle.normal.textColor = Color.yellow;
                    tempStyle.normal.background = m_NormalTexture;
                    try
                    {
                        m_KeyData.GetKey()[i] = GUI.TextField(new Rect (0,i*20 + 20, 100,20),m_KeyData.GetKey()[i], tempStyle);
                     
                        if (GUI.Button(new Rect(100, i * 20 + 20, 20, 20), "X"))
                        {
                            m_KeyData.DeleKey(m_KeyData.GetKey()[i]);
                        }
                    }
                    catch { }
                }
                
                //EditorGUILayout.EndVertical();
                EditorGUILayout.EndScrollView();

                if (GUI.Button(new Rect(0, 510, 20, 20), "X"))
                {
                    m_AddKey = string.Empty;
                }
                
                m_AddKey = GUI.TextField(new Rect (20,510,100,20),m_AddKey);

                if (GUI.Button(new Rect(120, 510, 20, 20), "+"))
                {
                    m_KeyData.AddKey(m_AddKey);
                }

                EditorGUILayout.EndVertical();
            }
            GUILayout.EndArea();

            if (GUI.Button(new Rect(660, 400, 60, 30), "Save"))
            {
                Save();
            }

            GUILayout.BeginArea(m_WindowsRect);
            {
                EditorGUILayout.BeginHorizontal();

                One_scrollPos = EditorGUILayout.BeginScrollView(One_scrollPos, false, false, GUILayout.Width(745), GUILayout.Height(470));

                GUIUtility.ScaleAroundPivot(m_Scale, new Vector2(Screen.width / 2, Screen.height / 2));

                if (m_IsShowArrow)
                {
                    DrawStateCurve(m_MousePoint, new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0), null, null, -1);

                    if (m_CurrentScript != null)
                    {
                        foreach (var item in m_CurrentScript.m_AllState)
                        {
                            if (item.ViewPositon.Contains(Event.current.mousePosition) && m_MousePoint != item.ViewPositon)
                            {
                                if (m_MousePoint == m_EnterRect)
                                {
                                    m_CurrentScript.m_AllState.Insert(0, item);
                                    m_IsShowArrow = false;
                                    break;
                                }
                                else
                                {
                                    if (m_CurrentSelect != null)
                                    {
                                        if (m_CurrentSelect.Relation == null)
                                        {
                                            m_CurrentSelect.Relation.m_NextData = new List<relationData>();
                                        }
                                        else
                                        {
                                            string tempKey = "isKey";
                                            int index = 0;
                                            Debug.Log("检测是否相同");
                                            for (int i = 0; i < m_CurrentSelect.Relation.m_NextData.Count; i++)
                                            {
                                                if (tempKey.Equals(m_CurrentSelect.Relation.m_NextData[i].key) || index != 0)
                                                {
                                                    while ((tempKey +(++index).ToString()).Equals(m_CurrentSelect.Relation.m_NextData[i].key))
                                                    {
                                                    }
                                                }
                                            }
                                            if (index != 0)
                                            {
                                                tempKey += index.ToString();
                                            }
                                            m_CurrentSelect.Relation.m_NextData.Add(new relationData(tempKey, item));
                                            m_KeyData.AddKey(tempKey);
                                        }
                                        m_IsShowArrow = false;
                                    }
                                }
                            }
                        }
                    }
                }

                if (m_CurrentScript == null && m_ScriptList != null && m_ScriptList.Length > 0)
                {
                    m_CurrentScript = EntityCodeGenerator.GetData(m_ScriptList[m_CurrentIndex]);
                }
                else
                {
                    if (m_CurrentScript.m_AllState.Count > 0)
                    {
                        foreach (var item in m_CurrentScript.m_AllState)
                        {
                            if (item.Relation == null)
                            {
                                item.Relation = new relation();
                                item.Relation.m_NextData = new List<relationData>();
                            }
                            else
                            {
                                if (item.Relation.m_NextData == null)
                                    item.Relation.m_NextData = new List<relationData>();

                                if (item.Relation.m_NextData.Count > 0)
                                {
                                    for (int i = 0; i < item.Relation.m_NextData.Count; i++)
                                    {
                                        relationData state = item.Relation.m_NextData[i];
                                        StateData tempData = m_CurrentScript.m_AllState.Find(x => x.ID.Equals(state.data.ID));
                                        if (tempData != null)
                                        {
                                            Rect m_NewRect = tempData.ViewPositon;
                                            DrawStateCurve(item.ViewPositon, m_NewRect, item, state, i);
                                        }
                                    }
                                }
                            }
                        }
                        BeginWindows();

                        for (int i = 0; i < m_CurrentScript.m_AllState.Count; i++)
                        {
                            if (i >= m_CurrentScript.m_AllState.Count || m_CurrentScript.m_AllState[i] == null)
                                continue;
                            if (i == 0)
                            {
                                DrawStateCurve(m_EnterRect, m_CurrentScript.m_AllState[i].ViewPositon, null, null, i);
                            }
                            m_CurrentScript.m_AllState[i].ViewPositon = GUI.Window(i, m_CurrentScript.m_AllState[i].ViewPositon, DrawStateWindow, new GUIContent(m_CurrentScript.m_AllState[i].ID));
                        }
                        EndWindows();
                    }
                }

                if (m_CurrentScript != null)
                {
                    if (m_CurrentScript.Name == ScriptData.masterName)
                    {
                        if (GUI.Button(m_EnterRect, "GameEnter", tempStyle))
                        {
                        }
                    }
                    else
                    {
                        if (GUI.Button(m_EnterRect, "Enter", tempStyle))
                        {
                        }
                    }
                }

                EditorGUILayout.EndScrollView();

                GUILayout.Box("",
                GUILayout.Width(5),
                GUILayout.MaxWidth(5),
                GUILayout.MinWidth(5),
                GUILayout.ExpandHeight(true));

                EditorGUILayout.EndHorizontal();
            }

            GUILayout.EndArea();
        }

        void Save()
        {           

            EntityCodeGenerator.GeneratorJson(m_CurrentScript);

            m_CurrentScript.m_AllState.ForEach(x=> {StateCodeGenerator.CreateCode(x.ID);});
      
            StateCodeGenerator.insertcoding(m_CurrentScript);

            m_KeyData.SaveData();
        }

        void DrawStateWindow(int id)
        {
            try
            {
                if (m_CurrentScript.m_AllState[id].CanChange)
                {
                    m_CurrentScript.m_AllState[id].ID = GUI.TextField(new Rect(0, 0, 80, 20), m_CurrentScript.m_AllState[id].ID);

                    if (GUI.Button(new Rect(80, 0, 20, 20), "√"))
                    {
                        m_CurrentScript.m_AllState[id].CanChange = false;

                        int m_index = 0;
                        foreach (var item in m_CurrentScript.m_AllState)
                        {
                            if (item != m_CurrentScript.m_AllState[id])
                            {

                                if (m_CurrentScript.m_AllState[id].ID == item.ID || m_index != 0)
                                {
                                    ++m_index;
                                    while ((m_CurrentScript.m_AllState[id].ID + (m_index).ToString()) == item.ID)
                                    {
                                        m_index++;
                                    }
                                }                  
                            }
                        }
                        if(m_index != 0)
                        m_CurrentScript.m_AllState[id].ID += m_index.ToString();                      
                    }
                }
                else
                {
                    GUIStyle m_Style = new GUIStyle();
                    m_Style.normal.textColor = Color.black;

                    GUI.Button(new Rect(0, 15, 100, 35), "", m_Style);
                    if (!m_IsShowArrow)
                        GUI.DragWindow();
                }
            }
            catch { }
        }

        void EventDeal()
        {

            switch (Event.current.type)
            {
                case EventType.MouseUp:
                    m_CurrentSelect = null;
                    m_IsShowArrow = false;
                    m_MousePoint = new Rect(0,0,0,0);
                    break;
                case EventType.ScrollWheel:
                    if (Event.current.delta.y < 0)
                    {

                    }
                    if (Event.current.delta.y > 0)
                    {

                    }
                    break;
                case EventType.DragPerform:

                    break;
                case EventType.DragUpdated:

                    break;
                case EventType.DragExited:

                    break;

                case EventType.MouseDown:
                    if (Event.current.button == 1)
                    {
                        m_TempMousePoint = Event.current.mousePosition;
                        GenericMenu m_menu = new GenericMenu();
                        m_menu.AddItem(new GUIContent("CreateState"), false, Callback, "CreateState");
                        m_menu.ShowAsContext();
                        Event.current.Use();
                    }
                    else
                    {
                        if (m_CurrentScript == null)
                            return;

                        foreach (var item in m_CurrentScript.m_AllState)
                        {
                            Rect tempRect = item.ViewPositon;
                            tempRect.y += 60;
                            tempRect.y += tempRect.height / 2;
                            tempRect.height = tempRect.height / 2;

                            if (tempRect.Contains(Event.current.mousePosition))
                            {
                                m_CurrentSelect = item;
                                m_IsShowArrow = true;
                                m_MousePoint = item.ViewPositon;
                                return;
                            }
                        }

                        Rect re = m_EnterRect;
                        re.y += 60;

                        if (re.Contains(Event.current.mousePosition))
                        {
                            m_IsShowArrow = true;
                            m_MousePoint = m_EnterRect;
                        }
                    }
                    break;
                case EventType.KeyDown:
                    if (Event.current.keyCode == KeyCode.Delete)
                    {
                        if (m_CurrentScript == null)
                            return;

                        foreach (var item in m_CurrentScript.m_AllState)
                        {
                            Rect tempRect = item.ViewPositon;
                            tempRect.y += 60;

                            if (tempRect.Contains(Event.current.mousePosition))
                            {
                                m_CurrentScript.m_AllState.Remove(item);
                                this.Repaint();
                                return;
                            }
                        }
                    }
                    break;
            }
        }

        void Callback(object m_OB)
        {
            switch (m_OB.ToString())
            {
                case "CreateState":

                    if (m_CurrentScript == null)
                    {
                        return;
                    }
                    
                    StateData m_TempData = new QFramework.StateData("State");
                    m_TempData.ViewPositon = new Rect(m_TempMousePoint.x, m_TempMousePoint.y-60, 100, 50);
                    
                    m_CurrentScript.m_AllState.Add(m_TempData);
                    break;
            }
        }

        void DrawStateCurve(Rect start, Rect end, StateData m_data = null, relationData next = null, int id = 0)
        {
            Vector3 startPos = new Vector3(start.x + start.width, start.y + start.height / 2, 0);
            Vector3 endPos = new Vector3(end.x, end.y + end.height / 2, 0);
            Vector3 startTan = startPos + Vector3.right * 50;
            Vector3 endTan = endPos + Vector3.left * 50;

            Color shadowCol = new Color(0, 0, 0, 0.06f);

            for (int i = 0; i < 3; i++)
                Handles.DrawBezier(startPos, endPos, startTan, endTan, shadowCol, null, (i + 1) * 5);

            Handles.DrawBezier(startPos, endPos, startTan, endTan, Color.magenta, null, 1);

            Vector3 Point=(startPos+endPos)/2;
            if (!m_Bezier.ContainsKey(id))
            {
                Vector3[] point = Handles.MakeBezierPoints(startPos, endPos, startTan, endTan, 3);
                Point = point[1];
            }

            if (m_data != null && next != null)
            {
                if (!m_data.Relation.isChangKey)
                {

                    if (GUI.Button(new Rect(Point+Vector3.left * 15, new Vector2(60, 20)), next.key, "ExposablePopupMenu"))
                    {
                        m_data.Relation.isChangKey = true;
                    }
                }
                else
                {
                    relationData tdata = next;
                    if (tdata == null)
                        return;

                    tdata.key = GUI.TextField(new Rect(Point + Vector3.left * 15, new Vector2(60, 20)), tdata.key, "SearchTextField");
                    int index = 0;

                    if (tdata.key != null)
                    {
                        for (int i = 0; i < m_KeyData.GetKey().Count; i++)
                        {
                            if (m_KeyData.GetKey()[i] != tdata.key)
                                if (m_KeyData.GetKey()[i].Contains(tdata.key))
                                {
                                    m_KeyScrollPos = GUI.BeginScrollView(new Rect(Point + Vector3.up * 20, new Vector3(70, 100)), m_KeyScrollPos, new Rect(Point  + Vector3.up * 20, new Vector3(50, 120)), new GUIStyle(), new GUIStyle());
                                    index++;
                                    GUIStyle m_style = new GUIStyle();
                                    m_style.normal.textColor = Color.yellow;

                                    if (GUI.Button(new Rect(Point /*+ Vector3.left * 30*/ + Vector3.up * 20 * index, new Vector2(50, 20)), m_KeyData.GetKey()[i], m_style))
                                    {
                                        tdata.key = m_KeyData.GetKey()[i];
                                    }
                                    GUI.EndScrollView();
                                }
                        }
                    }


                    if (GUI.Button(new Rect(Point + Vector3.right * 60 + Vector3.left * 15, new Vector2(20, 20)), "√"))
                    {
                        m_data.Relation.isChangKey = false;

                        int Flag = 0;
                        for (int i = 0; i < m_data.Relation.m_NextData.Count; i++)
                        {
                            if(i!=id)
                            if (tdata.key.Equals(m_data.Relation.m_NextData[i].key) || Flag != 0)
                            {
                                while ((tdata.key + (++Flag).ToString()).Equals(m_data.Relation.m_NextData[i].key))
                                {
                                }
                            }
                        }
                        if (Flag != 0)
                        {
                            tdata.key += Flag.ToString();
                        }
                        m_KeyData.AddKey(tdata.key);
                    }
                }
            }

        }
    }
}